import java.util.*;

/**
 * @class NeighbouringInArrayNumbersFinder 
 *
 * This program implements Task 2 from the "Java Basics" chapter of "Java SE" training:
 * Finds two neighbouring numbers in an array with the smallest distance to each other.
 * The index of the first number should be outputted to the screen.
 * If exists more than one decision should be outputted only a first one.
 * 
 * @version 1.0
 * @date 2013-06-18
 * @author Inna Ianko
*/
public class NeighbouringInArrayNumbersFinder {
	
	public static final String PROGRAM_DESCRIPTION = 
				"This program will find two neighbouring numbers in an array\n " 
				+ "with the smallest distance to each other.\n "
				+ "The index of the first such number will be returned.";		
	public static final int ZERO = 0;		
	public static final int SIGN_TO_STOP_ASKING_DATA = ZERO;	
	public static final int ARRAY_NEED_TO_BE_COMPARED_MINIMUM_LENGTH = 2;	
	
	public static final String COMPLETE_ENETRING_INPUTS = "END";			
	public static final String COLON = ":";	
	public static final String SPACE = " ";
	public static final String NEXT_LINE = "\n";	
	public static final String LINES_SEPARATOR = 
			"----------------------------------------------------------------";
	public static final String ENTER_INPUT_MESSAGE =
			"Please enter positive integer number or '" 
			+ COMPLETE_ENETRING_INPUTS + "' to complete entering data";			
	public static final String RESULT_HEADER_MESSAGE = 
			"You have entred the next array:";
	public static final String RESULT_INDEX_MESSAGE =
			"Index of the first element with smallest distance is";
	public static final String DATA_ENTERED_NOT_CORRECT_MESSAGE =
			"You have entered invalid data.";		
			
	public static void main (String[] args) {
			
		printDescription(PROGRAM_DESCRIPTION);		
		
		int[] arrayToManipulate = createArrayUsingEnteredNumbers();								
		int resultIndex = findMostNeighbouringNumbersIndex(arrayToManipulate);
		
		printOutput(resultIndex, arrayToManipulate);			
	}

	public static int[] createArrayUsingEnteredNumbers() {
							
		int numberToAddToArray;		
		int[] arrayToManipulate = new int[1];
				
		do {		
		    numberToAddToArray = getInputPositiveNumber();
			if (numberToAddToArray != SIGN_TO_STOP_ASKING_DATA) {
				arrayToManipulate = addValueToArray(arrayToManipulate, 
						numberToAddToArray);
			} 				
		} while (numberToAddToArray != SIGN_TO_STOP_ASKING_DATA);
		
		return arrayToManipulate;
	}
	
	public static int getInputPositiveNumber() {
							
		String enteredText;			
		boolean dataEnteredIsValid;	
		
		do  {								
			enteredText = askUserForInput();	
			
			if (COMPLETE_ENETRING_INPUTS.equals(enteredText.toUpperCase())) {
				return ZERO;
			} else {
				dataEnteredIsValid = validateDataInput(enteredText);
			}				
		} while (!dataEnteredIsValid);
				
		return Integer.parseInt(enteredText);
	}
	
	public static String askUserForInput() {

		Scanner input = new Scanner(System.in);
		
		System.out.println(ENTER_INPUT_MESSAGE + COLON);
		return input.nextLine();
	}
	
	public static boolean validateDataInput(String enteredText) {
										
		try	{							
			if (Integer.parseInt(enteredText) > ZERO) {
				return true;
			} else {
				System.out.println(DATA_ENTERED_NOT_CORRECT_MESSAGE + NEXT_LINE);
			}					
		}
		catch (NumberFormatException exception) {			
				System.out.println(DATA_ENTERED_NOT_CORRECT_MESSAGE + NEXT_LINE);					
		}
		return false;		
	}
	
	public static int[] addValueToArray(int[] arrayToEnlarge, int value) {
		
		int lengthOfArray = arrayToEnlarge.length;
		int indexToAdd = lengthOfArray;
		
		if (arrayToEnlarge[indexToAdd-1] == ZERO) {
			arrayToEnlarge[indexToAdd-1] = value;	
		} else {
			++lengthOfArray;	
			arrayToEnlarge = Arrays.copyOf(arrayToEnlarge, lengthOfArray);					
			arrayToEnlarge[indexToAdd] = value;	
		}
		return arrayToEnlarge;
	}
		
	public static int findMostNeighbouringNumbersIndex(int[] arrayWithNumbers) {
		
		int result = ZERO;  	
		
        if (arrayWithNumbers.length > ARRAY_NEED_TO_BE_COMPARED_MINIMUM_LENGTH) {	
					
			int previousIndex;
			int distanceIntermediate;			
			int distanceMinimum = getDistance(arrayWithNumbers[arrayWithNumbers.length-1], 
								arrayWithNumbers[arrayWithNumbers.length-2]);			
						
			for (int currentIndex = (arrayWithNumbers.length - 1); 
					currentIndex >= 1; currentIndex--) {
					
				previousIndex = currentIndex - 1;					
				distanceIntermediate = getDistance(arrayWithNumbers[currentIndex],
											arrayWithNumbers[previousIndex]);
				
				if  (distanceIntermediate <= distanceMinimum) {				
					distanceMinimum = distanceIntermediate; 
					result = previousIndex;	
				} 
			}
		}
		return result;									
	}
	
	public static int getDistance(int first_value, int second_value) {
	
		int result = first_value - second_value;
		
		if (result < ZERO) {
			result = result*(-1);
		}	
		return result;
	}
	
	public static void printOutput(int indexToOutput, int[] arrayToManipulate) {
		
		System.out.print(NEXT_LINE + RESULT_HEADER_MESSAGE 
				+ SPACE + Arrays.toString(arrayToManipulate));	
		System.out.print(NEXT_LINE + RESULT_INDEX_MESSAGE
				+ COLON + SPACE + indexToOutput + NEXT_LINE);	
	}
		
	public static void printDescription(String description) {
		
		System.out.println(NEXT_LINE + LINES_SEPARATOR);
		System.out.println(NEXT_LINE + SPACE + description);
		System.out.println(LINES_SEPARATOR);
	}
}